home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / KDEB.C < prev    next >
C/C++ Source or Header  |  1994-05-27  |  10KB  |  435 lines

  1. /*****************************************************************************
  2.  * FILE: kdeb.c                                                              *
  3.  *                                         *
  4.  * DESC:                                     *
  5.  *      - support for kernel debugging                                       *
  6.  *      - kernel ptrace                                                      *
  7.  *                                         *
  8.  * Copyright (C) 1993,1994                                                   *
  9.  *    Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld             *
  10.  *    email: rainer@mathematik.uni-bielefeld.de                 *
  11.  *                                         *
  12.  *****************************************************************************/
  13.  
  14. #include "DPMI.H"
  15. #include "KDEB.H"
  16.  
  17. #include "PROCESS.H"
  18. #include "PTRACE.H"
  19. #include "DOSERRNO.H"
  20. #include "START32.H"
  21. #include "ADOSX32.H"
  22. #include "SIGNALS.H"
  23. #include "PRINTF.H"
  24.  
  25. #define SINGLE_STEP    0x100
  26. #define RESUME_FLAG    0x10000L
  27. #define FLAG_MASK    0x00000dd9L
  28. #define BREAKPOINT    0xcc
  29.  
  30. #define MAX_HARD    4
  31. #define BP_FLAG_MASK    0x0FFF
  32. #define BP_ENABLE    0x1000
  33. #define BP_DISABLE    0x2000
  34.  
  35. typedef struct {
  36.     DWORD   address;
  37.     WORD    handle;
  38.     WORD    flags;
  39.     DWORD   data;
  40.     DWORD   pt_address;
  41. } HardBreakPoint;
  42.  
  43. static HardBreakPoint hbp[MAX_HARD];
  44. static DWORD memaddress;
  45.  
  46. static int KDEB_set_hard_break(DWORD at_address, WORD flags)
  47. {
  48.     int i;
  49.  
  50.     if (!memaddress)
  51.     GetBaseAddress(GetCS(), & memaddress);
  52.  
  53.     for (i = 1; i < MAX_HARD; i++)
  54.     if (hbp[i].flags == 0)
  55.         break;
  56.     if (i >= MAX_HARD)
  57.     return -1;
  58.     if (SetDebugWatchpoint(memaddress + at_address,
  59.                flags & BP_FLAG_MASK, &hbp[i].handle)) {
  60.     puts("set_hard_break() error");
  61.     return -1;
  62.     }
  63.     else {
  64.     hbp[i].address = at_address;
  65.     hbp[i].flags = flags | BP_ENABLE;
  66.     return i;
  67.     }
  68. }
  69.  
  70. static int KDEB_del_hard_break(int no)
  71. {
  72.     if (no >= MAX_HARD || hbp[no].flags == 0)
  73.     return -1;
  74.  
  75.     if (hbp[no].flags & BP_DISABLE) {
  76.     /* already clear */
  77.     hbp[no].address = 0;
  78.     hbp[no].flags = 0;
  79.     hbp[no].handle = 0;
  80.     return 0;
  81.     }
  82.  
  83.     if (ClearDebugWatchpoint(hbp[no].handle)) {
  84.     puts("del_hard_break() error");
  85.     return -1;
  86.     }
  87.     else {
  88.     hbp[no].address = 0;
  89.     hbp[no].flags = 0;
  90.     hbp[no].handle = 0;
  91.     return 0;
  92.     }
  93. }
  94.  
  95. static int KDEB_disable_hard_break(int no)
  96. {
  97.     if (no <= 1 && no >= MAX_HARD)
  98.     return -1;
  99.     if (hbp[no].flags & BP_DISABLE)
  100.     return -1;
  101.     if (ClearDebugWatchpoint(hbp[no].handle)) {
  102.     puts("disable_hard_break() error");
  103.     return -1;
  104.     }
  105.     else {
  106.     hbp[no].flags &= BP_FLAG_MASK;
  107.     hbp[no].flags |= BP_DISABLE;
  108.     return 0;
  109.     }
  110. }
  111.  
  112. static int KDEB_enable_hard_break(int no)
  113. {
  114.     if (no <= 1 && no >= MAX_HARD)
  115.     return -1;
  116.     if (hbp[no].flags & BP_ENABLE)
  117.     return -1;
  118.     if (SetDebugWatchpoint(memaddress + hbp[no].address,
  119.             hbp[no].flags & BP_FLAG_MASK, &hbp[no].handle)) {
  120.     puts("enable_hard_break() error");
  121.     return -1;
  122.     }
  123.     else {
  124.     hbp[no].flags &= BP_FLAG_MASK;
  125.     hbp[no].flags |= BP_ENABLE;
  126.     return 0;
  127.     }
  128. }
  129.  
  130.  
  131. int KDEB_check_breakpoints(DWORD pc)
  132. {
  133.     int i;
  134.     WORD j;
  135.  
  136.     for (i = 0; i < MAX_HARD; i++)
  137.     if (hbp[i].flags & BP_ENABLE) {
  138.         j = 0;
  139.         GetStateDebugWatchpoint(hbp[i].handle, &j);
  140.         if (j)
  141.         ResetDebugWatchpoint(hbp[i].handle);
  142.     }
  143.     return ((i >= MAX_HARD) ? -1 : i);
  144. }
  145.  
  146. void KDEB_enable_breakpoints(void)
  147. {
  148.     int i;
  149.     for (i = 0; i < MAX_HARD; i++)
  150.     if ((hbp[i].flags & BP_DISABLE) && hbp[i].pt_address)
  151.         KDEB_enable_hard_break(i);
  152. }
  153.  
  154. void KDEB_disable_breakpoints(void)
  155. {
  156.     int i;
  157.     for (i = 0; i < MAX_HARD; i++)
  158.     if ((hbp[i].flags & BP_ENABLE) && hbp[i].pt_address)
  159.         KDEB_disable_hard_break(i);
  160. }
  161.  
  162.  
  163.  
  164. /* +++++++++++++ PTRACE in KERNEL +++++++++++++++++ */
  165.  
  166. /* crt0.s */
  167. extern unsigned long rsx_data_start;
  168. extern unsigned long rsx_data_ends;
  169.  
  170. /*
  171.  * simulate ptrace(pid,POKETEXT,address,BREAKPOINT/ORGINAL)
  172.  */
  173. static int KDEB_ptrace_poketext(DWORD address, DWORD value)
  174. {
  175.     int i;
  176.     DWORD bp = value;
  177.     DWORD bp_addr = address;
  178.  
  179.     for (i = 0 ; i <= 3 ; i++) {
  180.     if ((bp & 0xff) == BREAKPOINT)
  181.         break;
  182.     bp >>= 8;
  183.     bp_addr ++;
  184.     }
  185.  
  186.     /* ptrace: set breakpoint in text */
  187.     if (i <= 3) {
  188.     printf("POKETEXT new break %lX\n", address);
  189.     if ((i = KDEB_set_hard_break(bp_addr, BREAK_CODE)) > 0) {
  190.         KDEB_disable_hard_break(i);
  191.         hbp[i].data = value;
  192.         hbp[i].pt_address = address;
  193.         return 0;
  194.     }
  195.     else {
  196.         printf("POKETEXT break fail %lX\n", address);
  197.         return -1;
  198.     }
  199.     }
  200.     /* ptrace: delete breakpoint in text */
  201.     else {
  202.     for (i = 0; i < MAX_HARD; i++)
  203.         if (address == hbp[i].pt_address)
  204.         break;
  205.     if (i >= MAX_HARD) {
  206.         printf("POKETEXT address %lX\n", address);
  207.         * (DWORD *) address = value;
  208.     }
  209.     else {
  210.         printf("POKETEXT delete break %lX\n", address);
  211.         hbp[i].data = hbp[i].pt_address = 0;
  212.         KDEB_del_hard_break(i);
  213.     }
  214.     return 0;
  215.     }
  216. }
  217.  
  218. /*
  219.  * simulate ptrace(pid,PEEKTEXT,address, 0)
  220.  */
  221. static int KDEB_ptrace_peektext(DWORD address, DWORD * value)
  222. {
  223.     int i;
  224.  
  225.     for (i = 0; i < MAX_HARD; i++)
  226.     if (address == hbp[i].pt_address)
  227.         break;
  228.     if (i >= MAX_HARD) {
  229.     /* printf("PEEKTEXT address %lX\n", address); */
  230.     *value = * (DWORD *) address;
  231.     }
  232.     else {
  233.     /* printf("PEEKTEXT peek break %lX\n", address); */
  234.     *value = hbp[i].data;
  235.     }
  236.     return 0;
  237. }
  238.  
  239. /*
  240.  * simulate ptrace(pid,POKEDATA,address,value)
  241.  */
  242. static int KDEB_ptrace_pokedata(DWORD address, DWORD value)
  243. {
  244.     if (address < 4096 || address >= rsx_data_ends) {
  245.     puts("KDEB: illegal address");
  246.     return EMX_EINVAL;
  247.     }
  248.     if (address == (DWORD) & npz) {
  249.     puts("KDEB: don't touch npz");
  250.     return EMX_EINVAL;
  251.     }
  252.     * (DWORD *) address = value;
  253.     return 0;
  254. }
  255.  
  256. /*
  257.  * simulate ptrace(pid,PEEKDATA,address,0)
  258.  */
  259. static int KDEB_ptrace_peekdata(DWORD address, DWORD * value)
  260. {
  261.     if (address < 4096 || address >= rsx_data_ends) {
  262.     puts("KDEB: illegal address");
  263.     return EMX_EINVAL;
  264.     }
  265.     if (address == (DWORD) & npz) {
  266.     *value = (DWORD) RSX_PROCESS.cptr;
  267.     return 0;
  268.     }
  269.     *value = * (DWORD *) address;
  270.     return 0;
  271. }
  272.  
  273. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  274.  
  275.  
  276. int KDEB_ptrace(int request, DWORD addr, DWORD data, DWORD * ret)
  277. {
  278.     /* printf("KDEB %d %lX %lX\n", request, addr, data); */
  279.  
  280.     *ret = 0;
  281.  
  282.     switch (request) {
  283.  
  284.     case PTRACE_TRACEME:
  285.     case PTRACE_SESSION:
  286.     return 0;
  287.  
  288.     case PTRACE_PEEKTEXT:
  289.     case PTRACE_PEEKDATA:
  290.     if (addr > 0x10000L && addr < rsx_data_start)
  291.         return KDEB_ptrace_peektext(addr, ret);
  292.     else
  293.         return KDEB_ptrace_peekdata(addr, ret);
  294.  
  295.     case PTRACE_POKETEXT:
  296.     if (addr > 0x10000L && addr < rsx_data_start)
  297.         return KDEB_ptrace_poketext(addr, data);
  298.     else
  299.         return KDEB_ptrace_pokedata(addr, data);
  300.  
  301.     case PTRACE_EXIT:
  302.     KDEB_disable_breakpoints();
  303.     return 0;
  304.  
  305.     case PTRACE_PEEKUSER:
  306.     if (addr == 0x30) {    /* u_ar0  */
  307.         *ret = 0xE0000000 + ((DWORD) (UINT) & (RSX_PROCESS.regs));
  308.         return 0;
  309.     } else {        /* peek regs */
  310.         DWORD *peekat;
  311.         peekat = (DWORD *) (UINT) (addr);
  312.  
  313.         if (peekat < &(RSX_PROCESS.regs.gs) || peekat > &(RSX_PROCESS.regs.ss))
  314.         return EMX_EIO;
  315.  
  316.         *ret = *peekat;
  317.  
  318.         if (peekat == &(RSX_PROCESS.regs.eip)) {
  319.         int i;
  320.         for (i = 0; i < MAX_HARD; i++)
  321.             if (RSX_PROCESS.regs.eip == hbp[i].address)
  322.             break;
  323.         if (i < MAX_HARD)
  324.             (*ret)++;
  325.         }
  326.  
  327.         return 0;
  328.     }
  329.  
  330.     case PTRACE_POKEUSER:
  331.     /* don't change kernel registers ! */
  332.     *ret = data;
  333.     return 0;
  334.  
  335.     case PTRACE_STEP:
  336.     /* printf("PTRACE step\n"); */
  337.     RSX_PROCESS.regs.eflags |= SINGLE_STEP;
  338.     npz = RSX_PROCESS.cptr;
  339.     KDEB_rsx32_orgjmp();
  340.     return 0;
  341.  
  342.     case PTRACE_RESUME:
  343.     /* printf("PTRACE resume\n"); */
  344.     RSX_PROCESS.regs.eflags &= ~SINGLE_STEP;
  345.     npz = RSX_PROCESS.cptr;
  346.     KDEB_enable_breakpoints();
  347.     /* start first program */
  348.     if (npz == & process[2] && npz->regs.eip == 0x10000)
  349.         back_from_syscall();
  350.     KDEB_rsx32_orgjmp();
  351.     return 0;
  352.  
  353.     default:
  354.     return EMX_EIO;
  355.     }
  356. }
  357.  
  358. struct POPAD {
  359.     unsigned edi;
  360.     unsigned esi;
  361.     unsigned ebp;
  362.     unsigned esp;
  363.     unsigned ebx;
  364.     unsigned edx;
  365.     unsigned ecx;
  366.     unsigned eax;
  367. };
  368.  
  369. #define RSXREG RSX_PROCESS.regs
  370.  
  371. static unsigned rsx_eip;
  372. static unsigned rsx_flags;
  373. static unsigned rsx_esp;
  374.  
  375. void KDEB_debug_handler(void)
  376. {
  377.     KDEB_check_breakpoints(RSXREG.eip);
  378.     KDEB_disable_breakpoints();
  379.  
  380.     /*
  381.     printf("Debug fault at %04X:%08lX  efl=%08lX\n",
  382.     RSXREG.cs & 0xFFFF, RSXREG.eip, RSXREG.eflags);
  383.     */
  384.  
  385.     rsx_eip = RSXREG.eip;
  386.     RSX_PROCESS.p_status = PS_STOP;
  387.     RSX_PROCESS.wait_return = (SIGTRAP << 8) | 127;
  388.     RSX_PROCESS.p_flags |= PF_WAIT_WAIT;
  389.     RSX_PROCESS.cptr = npz;
  390.     npz = & process[1];
  391.     EAX = ECX = 0;
  392.     npz->p_status = PS_RUN;
  393.  
  394.     /* ptrace should go on other stack */
  395.     stackp16 -= 8000;
  396.  
  397.     back_from_syscall();
  398. }
  399.  
  400. volatile void KDEB_rsx32_orgjmp(void)
  401. {
  402.     struct POPAD pop;
  403.  
  404.     /* ptrace should go on other stack */
  405.     stackp16 += 8000;
  406.  
  407.     pop.eax = RSXREG.eax;
  408.     pop.ecx = RSXREG.ecx;
  409.     pop.edx = RSXREG.edx;
  410.     pop.ebx = RSXREG.ebx;
  411.     pop.esp = RSXREG.esp;
  412.     pop.ebp = RSXREG.ebp;
  413.     pop.esi = RSXREG.esi;
  414.     pop.edi = RSXREG.edi;
  415.  
  416.     rsx_eip = RSXREG.eip;
  417.     rsx_flags = RSXREG.eflags;
  418.     rsx_esp = RSXREG.esporg;
  419.  
  420. loop:
  421.     __asm__ __volatile (
  422.     "movl %0, %%esp \n\t"
  423.     "popa \n\t"
  424.     "nop \n\t"
  425.     "movl  _rsx_esp, %%esp \n\t"
  426.     "pushl _rsx_flags\n\t"
  427.     "pushl %%cs \n\t"
  428.     "pushl _rsx_eip \n\t"
  429.     "iret \n\t"
  430.     :
  431.     : "r" ((unsigned)&pop)
  432.     );
  433.     goto loop;
  434. }
  435.